﻿//ContinuousSecurityMarketDataStorage.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Storages
{
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Linq;

	using Ecng.Collections;

	using StockSharp.BusinessEntities;

	class ContinuousSecurityMarketDataStorage<T> : IMarketDataStorage<T>
	{
		private readonly Func<Security, IMarketDataStorage<T>> _getStorage;
		private readonly ContinuousSecurity _security;
		//private readonly string _path;
		private readonly Func<T, DateTime> _getTime;
		private readonly Func<T, Security> _getSecurity;

		public ContinuousSecurityMarketDataStorage(ContinuousSecurity security, object arg, Func<T, DateTime> getTime, Func<T, Security> getSecurity, Func<Security, IMarketDataStorage<T>> getStorage, IMarketDataDrive drive)
		{
			if (security == null)
				throw new ArgumentNullException("security");

			if (getTime == null)
				throw new ArgumentNullException("getTime");

			if (getSecurity == null)
				throw new ArgumentNullException("getSecurity");

			if (getStorage == null)
				throw new ArgumentNullException("getStorage");

			if (drive == null)
				throw new ArgumentNullException("drive");

			_getStorage = getStorage;
			_security = security;
			_getTime = getTime;
			_getSecurity = getSecurity;
			
			_arg = arg;
			Drive = drive;
		}

		IEnumerable<DateTime> IMarketDataStorage.Dates
		{
			get
			{
				return from innerSecurity in _security.InnerSecurities
							let range = _security.ExpirationJumps.GetActivityRange(innerSecurity)
					   from date in _getStorage(innerSecurity).Dates.Where(range.Contains)
					   select date;
			}
		}

		Type IMarketDataStorage.DataType
		{
			get { return typeof(T); }
		}

		Security IMarketDataStorage.Security
		{
			get { return _security; }
		}

		private readonly object _arg;

		object IMarketDataStorage.Arg
		{
			get { return _arg; }
		}

		public IMarketDataDrive Drive { get; private set; }

		public IMarketDataStorageDrive StorageDrive
		{
			get {	return Drive.GetStorageDrive(_security, typeof(T), _arg); }
		}
	

		//string IMarketDataStorage.Path
		//{
		//    get { return _path; }
		//}

		private bool _appendOnlyNew = true;

		bool IMarketDataStorage.AppendOnlyNew
		{
			get { return _appendOnlyNew; }
			set
			{
				_appendOnlyNew = value;
				_security.InnerSecurities.ForEach(s => _getStorage(s).AppendOnlyNew = value);
			}
		}

		public void Save(IEnumerable<T> data)
		{
			foreach (var group in data.GroupBy(_getSecurity))
			{
				_getStorage(group.Key).Save(group);
			}
		}

		public void Delete(IEnumerable<T> data)
		{
			foreach (var group in data.GroupBy(d => _getTime(d).Date))
			{
				GetStorage(group.Key).Delete(group);
			}
		}

		void IMarketDataStorage.Delete(IEnumerable data)
		{
			Delete((IEnumerable<T>)data);
		}

		void IMarketDataStorage.Delete(DateTime date)
		{
			GetStorage(date).Delete(date);
		}

		void IMarketDataStorage.Save(IEnumerable data)
		{
			Save((IEnumerable<T>)data);
		}

		IEnumerable IMarketDataStorage.Load(DateTime date)
		{
			return Load(date);
		}

		IMarketDataStorageDayMetaInfo IMarketDataStorage.GetMetaInfo(DateTime date)
		{
			return GetStorage(date).GetMetaInfo(date);
		}

		public IEnumerableEx<T> Load(DateTime date)
		{
			return GetStorage(date).Load(date);
		}

		private IMarketDataStorage<T> GetStorage(DateTime date)
		{
			return _getStorage(_security.GetSecurity(date));
		}
	}
}
